﻿using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using System.Text.RegularExpressions;

namespace Magic.System;

/// <summary>
/// 文件服务类
/// </summary>
[Injection]
public class FileService : IFileService
{
    private readonly UploadOptions _uploadOptions;
    private readonly IWebHostEnvironment _hostEnvironment;
    public FileService(IOptions<UploadOptions> uploadOptions, IWebHostEnvironment hostEnvironment)
    {
        _uploadOptions = uploadOptions.Value;
        _hostEnvironment = hostEnvironment;
    }
    private async Task<FileOutput> HandleUploadFile(IFormFile file, [Required] string uuid, string savePath = "")
    {
        if (file == null)
            throw new ApiException("文件不能为空");
        //存储路径
        var path = savePath;
        if (string.IsNullOrWhiteSpace(savePath))
        {
            path = _uploadOptions.Path;
            var reg = new Regex(@"(\{.+?})");
            var match = reg.Matches(path);
            match.ToList().ForEach(a =>
            {
                var str = DateTime.Now.ToString(a.ToString().Substring(1, a.Length - 2)); // 每天一个目录
                path = path.Replace(a.ToString(), str);
            });
        }
        if (!_uploadOptions.ContentType.Contains(file.ContentType))
            throw new ApiException("文件格式不支持");

        var sizeKb = (long)(file.Length / 1024.0); // 大小KB
        if (sizeKb > _uploadOptions.MaxSize)
            throw new ApiException("文件过大");
        //后缀
        var suffix = Path.GetExtension(file.FileName).ToLower();
        if (string.IsNullOrWhiteSpace(suffix))
        {
            var contentTypeProvider = GetFileExtensionContentTypeProvider();
            suffix = contentTypeProvider.Mappings.FirstOrDefault(u => u.Value == file.ContentType).Key;
            // 修改 image/jpeg 类型返回的 .jpe 后缀
            if (suffix == ".jpe")
                suffix = ".jpg";
        }
        //文件名
        var finalName = string.Concat(uuid, suffix);//最终文件名
        //文件路径
        var filePath = Path.Combine(_hostEnvironment.WebRootPath, path);
        if (!Directory.Exists(filePath))
            Directory.CreateDirectory(filePath);
        var realFile = Path.Combine(filePath, finalName);
        using (var stream = File.Create(realFile))
        {
            await file.CopyToAsync(stream);
        }
        return new FileOutput
        {
            suffix = suffix,
            full_url = realFile,
            topic = "default",
            admin_id = UserManager.UserId,
            url = $"{savePath}/{finalName}",
            width = 1,
            height = 1,
            name = finalName,
            size = sizeKb,
            mimetype = file.ContentType,
            storage = "local",
            sha1 = ""
        };
    }
    /// <summary>
    /// 上传文件
    /// </summary>
    /// <param name="file"></param>
    /// <param name="uuid"></param>
    /// <param name="path"></param>
    /// <returns></returns>
    public async Task<FileOutput> UploadFile([Required] IFormFile file, [Required] string uuid, string path)
    {
        return await HandleUploadFile(file, uuid, path);
    }
    /// <summary>
    /// 上传头像
    /// </summary>
    /// <param name="file"></param>
    /// <param name="uuid"></param>
    /// <returns></returns>
    public async Task<FileOutput> UploadAvatar([Required] IFormFile file, [Required] string uuid)
    {
        return await UploadFile(file, uuid, "Upload/Avatar");
    }

    /// <summary>
    /// 初始化文件 ContentType 提供器
    /// </summary>
    /// <returns></returns>
    public FileExtensionContentTypeProvider GetFileExtensionContentTypeProvider()
    {
        var fileExtensionProvider = new FileExtensionContentTypeProvider();
        fileExtensionProvider.Mappings[".iec"] = "application/octet-stream";
        fileExtensionProvider.Mappings[".patch"] = "application/octet-stream";
        fileExtensionProvider.Mappings[".apk"] = "application/vnd.android.package-archive";
        fileExtensionProvider.Mappings[".pem"] = "application/x-x509-user-cert";
        fileExtensionProvider.Mappings[".gzip"] = "application/x-gzip";
        fileExtensionProvider.Mappings[".7zip"] = "application/zip";
        fileExtensionProvider.Mappings[".jpg2"] = "image/jp2";
        fileExtensionProvider.Mappings[".et"] = "application/kset";
        fileExtensionProvider.Mappings[".dps"] = "application/ksdps";
        fileExtensionProvider.Mappings[".cdr"] = "application/x-coreldraw";
        fileExtensionProvider.Mappings[".shtml"] = "text/html";
        fileExtensionProvider.Mappings[".php"] = "application/x-httpd-php";
        fileExtensionProvider.Mappings[".php3"] = "application/x-httpd-php";
        fileExtensionProvider.Mappings[".php4"] = "application/x-httpd-php";
        fileExtensionProvider.Mappings[".phtml"] = "application/x-httpd-php";
        fileExtensionProvider.Mappings[".pcd"] = "image/x-photo-cd";
        fileExtensionProvider.Mappings[".bcmap"] = "application/octet-stream";
        fileExtensionProvider.Mappings[".properties"] = "application/octet-stream";
        fileExtensionProvider.Mappings[".m3u8"] = "application/x-mpegURL";
        return fileExtensionProvider;
    }
}


